/*
 * main.h
 *
 *  Created on: 19/05/2011
 *      Author: daniel
 */

#ifndef MAIN_H_
#define MAIN_H_

#include <list>
#include <float.h>
#include <math.h>
#include <string.h>

using namespace std;

class Node {

public:
	int nombre;
	double coordx;
	double coordy;
	Node(int nombreNodo, double cdx, double cdy);
	double distanciaEuc(Node n);
};

class Solution {

public:
	double **C;
	int cityNumber;
	int *tour;
	int *pos;
	double cost;
	double iniCost;
	int numIter;

	// Constructores
	Solution(int n);
	Solution(int n, vector<Node> nodelst);

	/**
	 * Recalcula el costo de la solucion.
	 * @return: El costo recalculado.
	 */
	double recomputeCost();

	/**
	 * Intercambia el contenido de las posiciones
	 * a y b.
	 * @param: int a, int b.
	 */
	Solution *swap(int a, int b);

	/**
	 * Intercambia dos arcos del camino.
	 * @param: dos enteros no consecutivos, correspondientes
	 * 		   a la ciudad inicial de los arcos que se quieren
	 * 		   intercambiar.
	 */
	Solution *flip(int a, int c);

	/**
	 * Retorna el costo de ir de a a b.
	 * @param: la posicion de la ciudad a y la de
	 * 		   la ciudad b.
	 */
	double getCost(int a, int b);

	/**
	 * Actualiza el costo de la solucion.
	 */
	void updateCost(int a, int b);

	/**
	 * Imprime la solucion.
	 */
	void print();

	/**
	 * Imprime por pantalla con formato.
	 */
	void printWithFormat();

	/**
	 * Escribe la solucion a un archivo.
	 */
	void write(char* fileName);

	/**
	 * Copia la solucion.
	 * @return: Una nueva solucion.
	 */
	Solution *clone();

	/**
	 * Invierte un segmento del tour.
	 * @param: la posicion inicial y final del
	 * 		   segmento.
	 */
	void reverse(int inicial, int final);

	Solution* reverseWay(int inicial, int final);

	int** updateLT(int min, int max, int size, int **LT);

	int** bestSolution(vector<int> neighbors, Solution* sMejor, int **LT);

	virtual ~Solution();
};

class Parser {
public:
	Parser();
	vector<Node> leerArchivo(char *nombreArchivo);
	virtual ~Parser();
};

class GA {
public:

	/**
	 * Aplica algoritmo genetico a una solucion.
	 */
	static Solution* geneticAlgorithm(Solution *problem, int tam,
			int generations, int k, int MaxChildren, double Ppair, double PMut,
			double greedyPercentage);
};

class SA {
public:
	/**
	 * Aplica recocido simulado.
	 * @return: Una solucion.
	 */
	static Solution *SimulatedAnnealing(Solution *is, int MaxIter, double alpha,
			double betha, int Temp, int K, int A);

};

class LS {
public:
	/**
	 * Aplica busqueda local a una solucion inicial.
	 * @param: un apuntador a una solucion inicial.
	 * @return: un optimo local.
	 */
	static Solution* LocalSearch(Solution *is, int maxIter, int stuck);

	/**
	 * Aplica busqueda local a una solucion inicial (Mejor-mejor).
	 * @param: un apuntador a una solucion inicial.
	 * @return: un optimo local.
	 */
	static Solution* LocalSearchBI(Solution *is, int maxIter, int stuck);

};

class ILS {
public:

	/**
	 *	Recibe una lista de nodos y construye una solucion
	 *	utilizando Busqueda Local Iterada.
	 *	@param: Un vector con todos los nodos.
	 *	@return: Una solucion.
	 */
	static Solution* Ils(Solution *is, int MaxIter, int stuck);

};

class Operator {
public:
	Operator();
	virtual ~Operator();

	/**
	 * Perturba la solucion intercambiando arcos.
	 * @param: Una solucion y el grado de perturbacion que
	 * 		   se desea.
	 */
	Solution *flipArcs(Solution *s, int step, int ini, int fin);

	/**
	 * Retorna un conjunto de movimientos 2-opt.
	 */
	static vector<int*> twoOptNeighborhood(Solution *s);

	/**
	 * Encuentra una vecindad para una solucion.
	 * @param: una solucion y un grado de variacion.
	 * @return: Un vector con los intercambios que
	 *          construyen la vecindad.
	 */
	static vector<int> neighbors(Solution *sact, int paso);

	/**
	 * Retorna una solucion nueva a partir de otra.
	 * @param: Una solucion.
	 * @return: Una solucion.
	 */
	static Solution *perturbation(Solution *s);

	/**
	 * Retorna el mejor movimiento 2-Opt.
	 * @param: Una solucion.
	 * @return: int[2] a intercambiar.
	 */
	static int* twoOptMove(Solution *s);

};

class AC {
public:

	static Solution* AntColonyMinMax(vector<Node> nodelist, int maxIter, int numAnt,
			double tmax, double tmin, double alpha, double betha);

};

class TABU {
public:
	static Solution* TABUSearch(Solution* is, int maxIter, int maxNoMejora, int LTsize);

	static int nearestNeighbor(int i, Solution *s, vector<int> noVisitados);
};


class GRASP {
public:
	GRASP();
	virtual ~GRASP();

	static Solution *GreedyRandomizedConstruction(Solution *problem,
			float alpha);
	static Solution *Grasp(Solution *problem, int MaxIter, double alpha,
			int maxStuck, int greedy);
	static Solution *SampleGreedy(Solution *problem, double alpha);
	static Solution *Greedy(Solution *problem, double alpha);

};

class Constructive {
public:
	Constructive();

	/*
	 * Construye soluciones greedy aleatorias.
	 * @param: Un grado de voracidad.
	 * @return: Una solucion.
	 */
	static Solution *GreedyRandomizedConstruction(Solution *problem,
			float alpha);

	/**
	 * Aplica Grasp a un conjunto de ciudades para
	 * obtener el tour.
	 * @param: Una solucion inicial. (Problema), un parametro
	 * 		   alpha correspondiente al greedyness.
	 * @return: Solucion.
	 *
	 */
	static Solution *GRASP(Solution *problem, int MaxIter, float alpha);

	virtual ~Constructive();
};

#endif /* MAIN_H_ */
